﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Metriks.Parsiranje
{
    public static class KvaziRegex
    {
        private static Regex emptyLineRegex = new Regex(@"^\s*$");
        private static Regex commentLineRegex = new Regex(@"^//([^$]*)$");
        private static Regex vardeclRegex = new Regex(@"^(int|double)\s(\w+);$");
        private static Regex beginFunctionRegex = new Regex(@"^function\s(\w+)\(([^\)]*)\)\sreturns\s(void|int|double)$");
        private static Regex miniVarRegex = new Regex(@"(int|double)\s(\w+)");
        private static Regex varInitRegex = new Regex(@"^(int|double)\s(\w+)=([^;]+);$");
        private static Regex varAssignRegex = new Regex(@"^(\w+)=([^;=]+);$");
        private static Regex beginIfRegex = new Regex(@"^if\s\(([^\)]{3,})\)\sthen$");
        private static Regex beginElsifRegex = new Regex(@"^elsif\s\(([^\)]{3,})\)\sthen$");
        private static Regex beginWhileRegex = new Regex(@"^while\s\(([^\)]{3,})\)\sdo$");
        private static Regex returnLOCRegex = new Regex(@"^return\s([^;]+);$");

        private static String[] extractRegexMatch(Match m)
        {
            List<String> rez = m.Groups.Cast<Group>().Select(y => y.Value).ToList<String>();
            rez.RemoveAt(0);
            return rez.ToArray();
        }

        public static String[] matchEmptyLine(String input)
        {
            if (emptyLineRegex.IsMatch(input))
                return new String[] { "" };
            else
                return null;
        }

        public static String[] matchCommentLine(String input)
        {
            if (commentLineRegex.IsMatch(input))
                return extractRegexMatch(commentLineRegex.Match(input));
            else
                return null;
        }

        public static String[] matchBeginFunction(String input)
        {
            List<String> rezultat = new List<String>();
            if (beginFunctionRegex.IsMatch(input))
            {
                String[] imeITipFunkcije = extractRegexMatch(beginFunctionRegex.Match(input));
                rezultat.Add(imeITipFunkcije[0]); // dodajemo ime funkcije pronađeno u regexu
                // sad vadimo varijable

                try
                {
                    rezultat.AddRange(povadiVarijable(imeITipFunkcije[1]));
                }
                catch (VarijablaNeValjaException evne)
                {
                    throw evne;
                }
                catch (Exception)
                {

                }

                rezultat.Add(imeITipFunkcije[2]); // dodajemo tip funkcije pronađem u regexu
                return rezultat.ToArray();
            }
            else
                return null;

        }

        public static String[] matchEndFunction(String input)
        {
            if (input == "endfunction")
                return new String[] { };
            else
                return null;
        }

        public static String[] matchVarDecl(String input)
        {
            if (vardeclRegex.IsMatch(input))
                return extractRegexMatch(vardeclRegex.Match(input));
            else
                return null;
        }

        public static String[] matchVarInit(String input)
        {
            if (varInitRegex.IsMatch(input))
            {
                String[] tipnazivizraz = extractRegexMatch(varInitRegex.Match(input));
                if (!aritExprOK(tipnazivizraz[2]))
                    return null;
                return tipnazivizraz;
            }
            else
                return null;
        }

        public static String[] matchVarAssign(String input)
        {
            if (varAssignRegex.IsMatch(input))
            {
                String[] nazivizraz = extractRegexMatch(varAssignRegex.Match(input));
                if (!aritExprOK(nazivizraz[1]))
                    return null;
                return nazivizraz;
            }
            else
                return null;
        }

        public static String[] matchBeginIf(String input)
        {
            if (beginIfRegex.IsMatch(input))
            {
                String[] izraz = extractRegexMatch(beginIfRegex.Match(input));
                if (!logicalExprOK(izraz[0]))
                    return null;
                return izraz;
            }
            else
                return null;
        }

        public static String[] matchBeginElsif(String input)
        {
            if (beginElsifRegex.IsMatch(input))
            {
                String[] izraz = extractRegexMatch(beginElsifRegex.Match(input));
                if (!logicalExprOK(izraz[0]))
                    return null;
                return izraz;
            }
            else
                return null;
        }

        public static String[] matchBeginElse(String input)
        {
            if (input == "else")
                return new String[] { };
            else
                return null;
        }

        public static String[] matchEndif(String input)
        {
            if (input == "endif")
                return new String[] { };
            else
                return null;
        }

        public static String[] matchEndWhile(String input)
        {
            if (input == "endwhile")
                return new String[] { };
            else
                return null;
        }

        public static String[] matchBeginWhile(String input)
        {
            if (beginWhileRegex.IsMatch(input))
            {
                String[] izraz = extractRegexMatch(beginWhileRegex.Match(input));
                if (!logicalExprOK(izraz[0]))
                    return null;
                return izraz;
            }
            else
                return null;
        }

        public static String[] matchReturn(String input)
        {
            if (returnLOCRegex.IsMatch(input))
                return extractRegexMatch(returnLOCRegex.Match(input));
            else
                return null;
        }

        /// <summary>
        /// Ulaz je ili prazan ili int x ili int x, double y etc
        /// </summary>
        /// <param name="ulaz"></param>
        /// <returns></returns>
        public static List<String> povadiVarijable(String ulaz)
        {
            List<String> tipVar = new List<String>();
            if (ulaz == "")
                throw new Exception();
            String[] pojedinacneVarijable = ulaz.Split(',');
            for (int i = 0; i < pojedinacneVarijable.Length; i++)
            {
                pojedinacneVarijable[i] = pojedinacneVarijable[i].Trim();
                tipVar.AddRange(izvadiVarijablu(pojedinacneVarijable[i]));
            }

            return tipVar;
        }

        public static String[] izvadiVarijablu(String varcontext)
        {
            if (miniVarRegex.IsMatch(varcontext))
                return extractRegexMatch(miniVarRegex.Match(varcontext));
            else
                throw new VarijablaNeValjaException();
        }

        // TODO ako budem imao vremena @Hidex
        // update @ 27.5. nemam vremena :(
        public static bool aritExprOK(String s)
        {
            return true;
        }

        // TODO ako budem imao vremena @Hidex
        // update @ 27.5. nemam vremena :(
        public static bool logicalExprOK(String s)
        {
            return true;
        }
    }

    public class VarijablaNeValjaException : Exception
    {
    }
}
